import json
import base64
from hashlib import md5
from FooderErrno import error_no
from .aes_tool import AesTool

class FooderAuthenticationError(RuntimeError):
    def __init__(self, code, message):
        self.code = code
        self.message = message

ErrServerTokenNull = FooderAuthenticationError(10000, "not detected token")
ErrServerTokenParse = FooderAuthenticationError(10001, "token parse fail")
ErrServerTokenPackage = FooderAuthenticationError(10002, "token format error")
ErrServerUnauthorized = FooderAuthenticationError(10003, "device not authorized")
ErrServerTokenBody = FooderAuthenticationError(10004, "body content tampered with")

def filter(event, aeskey, LOCAL, deviceId, shopId):
    """统一接口鉴权"""
    '''
    返回值：解析的body体<class dict>
    deviceId: 终端设备唯一标识
    shopId: 终端设备对应的商家Id
    '''
    if LOCAL:
        with open('event.evt', 'r') as f:
            event = f.read()
    # 解析event参数
    evt_list = json.loads(event)
    # 解析header
    headers = evt_list['headers']
    if 'Access_token' not in headers:
        raise ErrServerTokenNull

    # 解析Access_token
    aes_token = headers['Access_token']
    aes = AesTool(aeskey, aeskey)
    try:
        token_parse = aes.decode(aes_token)
    except Exception:
        raise ErrServerTokenParse

    # Access_token生成规则：AES(shopId:md5(body))
    if ':' not in token_parse:
        raise ErrServerTokenPackage

    # 解析 shopId 与 md5(body)
    tokens = token_parse.split(':')
    deviceId.append(tokens[0])
    md5body = tokens[1]
    # Redis中确定设备是否被运维平台授权，根据deviceId查询shopId
    if 0:
        raise ErrServerUnauthorized

    # 解析base64编码的body
    isbase64 = evt_list['isBase64Encoded']
    if isbase64:
        body = base64.b64decode(evt_list['body'])
    else:
        body = evt_list['body']
    # 计算body的md5
    # body=b'xxx', type=<class 'bytes'> --> body.decode() 默认为utf8编码转为string
    bodymd5 = md5(body.decode().encode('utf-8')).hexdigest()
    if md5body.lower() != bodymd5.lower():
        raise ErrServerTokenBody

    # 解析 body json
    j_data = json.loads(body)
    return j_data
